//
//  PlayerView.swift
//  HaiLuo
//
//  Created by Rowling on 2020/5/29.
//  Copyright © 2020 Rowling. All rights reserved.
//

import UIKit
import RxRelay

protocol PlayerViewDelegate : NSObject{
    func onError(_ player: AliPlayer!, errorModel: AVPErrorModel!)
    func onPlayerEvent(_ player: AliPlayer!, eventType: AVPEventType)
    /**广告播放完成*/
    func advertisementPlayOver(_ player: AliPlayer!)
    /**广告点击*/
    func adVertiseClick()
    /**开通vip*/
    func openVIPClick()
    /**购买此集*/
    func buyTheVideo()
    /**播放中进度回调*/
    func onCurrentPositionUpdate(_ player: AliPlayer!, position: Int64)
    /**播放完成*/
    func playeVedioOver(_ player: AliPlayer!)
    /**收藏点击*/
    func lickButtonClick(button : UIButton)
    /**下载点击*/
    func downLoadClick(button : UIButton)
    /**点击摸一个剧集*/
    func didCLickJuji(index : Int)
    /**下一集*/
    func playNextVideo()
}

extension PlayerViewDelegate {
    func onError(_ player: AliPlayer!, errorModel: AVPErrorModel!) {}
    func onPlayerEvent(_ player: AliPlayer!, eventType: AVPEventType) {}
    func advertisementPlayOver(_ player: AliPlayer!) {}
    func adVertiseClick() {}
    func openVIPClick(){}
    func buyTheVideo(){}
    func onCurrentPositionUpdate(_ player: AliPlayer!, position: Int64){}
    func playeVedioOver(_ player: AliPlayer!){}
    func lickButtonClick(button : UIButton){}
    func downLoadClick(button : UIButton){}
    func didCLickJuji(index : Int){}
    func playNextVideo(){}
}

class PlayerView: UIView {
    enum VideoType {
        case advertisement // 广告
        case normal      // 正片
    }
    
    
    
    var disposeBag = DisposeBag()
    /**底部父视图*/
    var playerBottomView : PlayerViewBottomView!
    /**顶部父视图*/
    var playerTopView : PlayerTopView!
    /**播放画面的视图*/
    var playVedioView : UIView!
    var gestureView : AliyunPlayerViewGestureView!
    private let timer = Observable<Int>.timer(.seconds(0), period: .seconds(1), scheduler: MainScheduler.instance)
    /**阿里播放器*/
    lazy var player : AliPlayer = {
       let a = AliPlayer()!
        a.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT
        return a
    }()
    /**播放状态*/
//    var playStatus :  AVPStatus = AVPStatusIdle
    
    var playStatus = BehaviorRelay(value: AVPStatusIdle)
    
    var bottomH : CGFloat = 50
    let topViewH : CGFloat = 50
    var isProtrait = true
    var bottomViewStartProgress : CGFloat = 0
    var lastOptiontime = 0 // 上次操作过的时间 （秒）
    
    var videoType : VideoType = .normal {
        didSet {
            if videoType == .advertisement {
                hideRightNow()
            }
        }
    }
    
    /**是否是播放的本地视频*/
    var isCachePlayer = false
    /**本地播放结束回调*/
    var cacheStop : (()->())?
    weak var delegate : PlayerViewDelegate?
    /** 活动指示器*/
    var indicator : UIActivityIndicatorView!    
    /**标题*/
    var title = "" {
        didSet{
            playerTopView.backBtn.setTitle(title, for: .normal)
        }
    }
        
//    /**没有网络View*/
//    lazy var noNetView : UIView = {
//        let v = UIView()
//        let label = ZMUtil.label(title: "当前无可用网络，请连接后重试[1.101]", color: "#CCCCCC".zm.hex(), font: UIFont.systemFont(ofSize: 14))
//        v.addSubview(label)
//        label.snp.makeConstraints { (make) in
//            make.center.equalToSuperview()
//        }
//        v.backgroundColor = UIColor.black
//        return v
//    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUI()
        addObser()
        bindAction()
        timerOn()
//        enableLog
    }
    
    func addObser() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleDeviceOrientationDidChange(interfaceOrientation:)), name: UIDevice.orientationDidChangeNotification, object: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setUI() {
        playVedioView = UIView()
        addSubview(playVedioView)
        playVedioView.backgroundColor = UIColor.black
        playVedioView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        
        player.playerView = playVedioView
        player.delegate = self
        
        gestureView = AliyunPlayerViewGestureView()
        gestureView.delegate = self
        addSubview(gestureView)
        
        playerBottomView = PlayerViewBottomView(frame: CGRect(x: 0, y: 0, width: SCREEN_W, height: bottomH))
        playerBottomView.delegate = self
        addSubview(playerBottomView)
        playerTopView = PlayerTopView(frame: CGRect(x: 0, y: 0, width: SCREEN_W, height: bottomH))
        addSubview(playerTopView)
        
        // 初始化菊花
        indicator = UIActivityIndicatorView(style: .white)
    }
    
    func showindicator() {
        addSubview(indicator)
        indicator.snp.makeConstraints { (make) in
           make.center.equalToSuperview()
        }
        indicator.startAnimating()
    }
    
    func hideindicator() {
        indicator.stopAnimating()
        indicator.removeFromSuperview()
    }
    
    //MARK:绑定事件
    func bindAction() {
        playerTopView.backBtn.rx.tap.subscribe { [weak self] (_) in
            guard let self = self else {return}
            if self.isProtrait {
                // 导航返回
//                self.yy_viewController?.navigationController?.popViewController(animated: true)
            } else {
                // 旋转
                AliyunUtil.setFullOrHalfScreen()
                if self.isCachePlayer {
                    // 是在播放本地缓存的视频
                    // 这个时候应该停止播放
                    self.player.stop()
                    if let cacheStop = self.cacheStop {
                        cacheStop()
                    }
                }
            }
        }.disposed(by: disposeBag)
        
        NotificationCenter.default.rx.notification(UIApplication.didBecomeActiveNotification, object: nil).subscribe {[unowned self] (noti) in
            self.player.start()
        }.disposed(by: disposeBag)
        
        NotificationCenter.default.rx.notification(UIApplication.willResignActiveNotification, object: nil).subscribe { [unowned self] (noti) in
            self.player.pause()
        }.disposed(by: disposeBag)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        playerBottomView.frame = CGRect(x: 0, y: zm.height - bottomH, width: zm.width, height: bottomH)
        playerTopView.frame = CGRect(x: 0, y: 0, width: zm.width, height: topViewH)
        gestureView.frame = CGRect(x: 0, y: 0, width: zm.width, height: zm.height)
    }
    
    //MARK:屏幕旋转处理
    @objc func handleDeviceOrientationDidChange(interfaceOrientation : UIInterfaceOrientation) {
        let d = UIDevice.current
        if d.orientation == .portrait {
            isProtrait = true
            playerBottomView.isProtrait = true
        } else if d.orientation == .landscapeLeft || d.orientation == .landscapeRight {
            isProtrait = false
            playerBottomView.isProtrait = false
        }
    }
    
    
    //MARK:--------------------播放事件--------------------
    // 播放
    func play(source : AVPVidStsSource) {
        player.isAutoPlay = true
        player.setStsSource(source)
        showindicator()
        player.prepare()
    }
    // 播放
    func play(source : AVPUrlSource) {
        player.isAutoPlay = true
        player.setUrlSource(source)
        showindicator()
        player.prepare()
    }
    // 播放广告
    func playAd(source : AVPVidStsSource) {
        player.isAutoPlay = true
        player.setStsSource(source)
        showindicator()
        player.prepare()
    }
    
    //播放试看
    func playTryLook(source : AVPVidStsSource) {
        player.isAutoPlay = true
        player.setStsSource(source)
        showindicator()
        player.prepare()
    }
        
    func timeInfoFill() {
        let cmin = player.currentPosition / 1000 / 60
        let csecond = (player.currentPosition / 1000) % 60
        let currentStr = String.init(format: "%02d", cmin) + ":" + String.init(format: "%02d", csecond)
        let allMin = player.duration / 1000 / 60
        let allsecond = (player.duration / 1000) % 60
        let allurrentStr = String.init(format: "%02d", allMin) + ":" + String.init(format: "%02d", allsecond)
        playerBottomView.playTimeLabel.text = currentStr
        playerBottomView.allTimeLabel.text = allurrentStr
        playerBottomView.ProgressView.progress = Float(player.currentPosition) / Float(player.duration)
    }
    
    //MARK:开始播放操作或者暂停
    func puseOrStart() {
        if playStatus.value == AVPStatusPaused {
            player.start()
        } else if playStatus.value == AVPStatusStarted {
            player.pause()
        } else if playStatus.value == AVPStatusCompletion {
            // 播放完成
            player.seek(toTime: 0, seekMode: AVP_SEEKMODE_ACCURATE)
            player.start()
        }
    }
    
    func start() {
        player.start()
    }
    
    func pause() {
        player.pause()
    }
    
    //MARK:------------------------------------------自动隐藏上下view 相关方法--------------------------------------------------------
    //计时器操作
    func timerOn() {
        let hide = timer.take(until: rx.deallocated).map({[weak self] (_) -> Bool in
            guard let self = self else {return false}
            self.lastOptiontime += 1
            return self.lastOptiontime >= 5
        })
        hide.map { [weak self] (ok) -> Bool in
            guard self != nil else {return false}
           return ok
        }.bind(to: playerBottomView.rx.isHidden).disposed(by: disposeBag)
        
        hide.map { [weak self] (ok) -> Bool in
            guard self != nil else {return false}
           return ok
        }.bind(to: playerTopView.rx.isHidden).disposed(by: disposeBag)
    }
    // 立刻隐藏
    func hideRightNow() {
        lastOptiontime = 5
        playerBottomView.isHidden = true
        playerTopView.isHidden = true
    }
    // 立刻显示
    func showRightNow() {
        // 广告模式不显示操作栏
        if videoType == .advertisement {return}
        lastOptiontime = 0
        playerBottomView.isHidden = false
        playerTopView.isHidden = false
    }
  
    deinit {
        player.destroy()
        print("播放器已经销毁")
    }
}

//MARK:AVPDelegate
extension PlayerView : AVPDelegate {
    //MARK:播放器事件回调
    func onPlayerEvent(_ player: AliPlayer!, eventType: AVPEventType) {
        switch eventType {
        case AVPEventPrepareDone:
            print("准备完成事件")
            hideindicator()
        case AVPEventAutoPlayStart:
            print("自动启播事件")
//            if currentPlayType == .tryLook {
//                // 试看
//                let time = player.duration / 1000
//                let min = Int(time) / 60
//                let str = String(format:"试看%d分钟，观看全片请 开通会员".local,min)
//                let atr = str.zm.attributedStr(subString: "开通会员".local, attrs: [NSAttributedString.Key.foregroundColor : UIColor.zm.color(hexString: "#E2B355")])
//                shikanBtn.setAttributedTitle(atr, for: .normal)
//                shikanBtn.isHidden = false
//            }
            
        case AVPEventFirstRenderedStart:
            print("首帧显示事件")
            hideindicator()

        case AVPEventCompletion:
            print("播放完成事件")
            delegate?.playeVedioOver(player)
        case AVPEventLoadingStart:
            print("缓冲开始事件")
            showindicator()
        case AVPEventLoadingEnd:
            print("缓冲完成事件")
            hideindicator()
        case AVPEventSeekEnd:
            print("跳转完成事件")
        case AVPEventLoopingStart:
            print("循环播放开始事件")
        default:
            break
        }
        if let delegate = delegate {
            delegate.onPlayerEvent(player, eventType: eventType)
        }
    }
    //MARK: 缓冲进度
    func onBufferedPositionUpdate(_ player: AliPlayer!, position: Int64) {
            playerBottomView.ProgressView.loadTimeProgress = Float(position) / Float(player.duration)
    }

    //MARK: 播放中进度回调
    func onCurrentPositionUpdate(_ player: AliPlayer!, position: Int64) {
        if !playerBottomView.isDrag {
            timeInfoFill()
        }
        self.delegate?.onCurrentPositionUpdate(player,position: position)
    }
    
    //MARK: 出错回调
    func onError(_ player: AliPlayer!, errorModel: AVPErrorModel!) {
        hideindicator()
        if let delegate = delegate {
            delegate.onError(player, errorModel: errorModel)
        }
    }
    
    //MARK:播放器状态回调
    func onPlayerStatusChanged(_ player: AliPlayer!, oldStatus: AVPStatus, newStatus: AVPStatus) {
        playStatus.accept(newStatus)
        switch newStatus {
        case AVPStatusPrepared:
            // 准备完成
            print("准备完成")
        case AVPStatusStarted:
            //正在播放
            print("正在播放")
            playerBottomView.playBtn.isSelected = true
        case AVPStatusPaused:
            //播放暂停
            print("播放暂停")
            playerBottomView.playBtn.isSelected = false
        case AVPStatusStopped:
            //播放停止
            print("播放停止")
            playerBottomView.playBtn.isSelected = false
        case AVPStatusCompletion:
            //播放完成
            print("播放完成")
            playerBottomView.playBtn.isSelected = false
        case AVPStatusError:
            //播放错误
            print("播放错误")
            playerBottomView.playBtn.isSelected = false
        default:
            break
        }
    }
}


//MARK: PlayerViewBottomViewDelegate
extension PlayerView : PlayerViewBottomViewDelegate {

    func playNextClick() {
        delegate?.playNextVideo()
    }
    
    func downLoadClick(button: UIButton) {
        delegate?.downLoadClick(button: button)
    }
    
    func lickButtonClick(button: UIButton) {
        delegate?.lickButtonClick(button: button)
    }
    
   
    func playBtnClick(button: UIButton) {
        puseOrStart()
        showRightNow()
    }
    
    func sliderVauleDidChange(value: Float) {
        if !canSeek(){return}
        let theTime = Int(Float(player.duration) * value)
        let cmin = theTime / 1000 / 60
        let csecond = (theTime / 1000) % 60
        let currentStr = String.init(format: "%02d", cmin) + ":" + String.init(format: "%02d", csecond)
        playerBottomView.playTimeLabel.text = currentStr
        showRightNow()
    }
    
    
    func onClickedfullScreenButton() {
        showRightNow()
    }
    
    func sliderDidEndDrag(value: Float) {
        if !canSeek(){return}
        showRightNow()
        player.seek(toTime: Int64(Float(player.duration) * value), seekMode: AVP_SEEKMODE_ACCURATE)
    }
    
    //MARK:剧集点击
    func listButtonClick() {
//        showMovieListView()
    }
    
    // 分享点击
    func shareButtonClick() {
//        guard let videoDetial = videoDetial else {return}
//        let share = LandScapeShareView.shareView("http://www.baidu.com",videoDetial.showImgSmall,videoDetial.contentName, videoDetial.introduce)//Bundle.main.loadNibNamed("LandScapeShareView", owner: nil, options: nil)?.first as! LandScapeShareView
//        share.frame = CGRect(x: 0, y: 0, width: zm.width, height: zm.Height)
//        share.animationMode = FromRight
//        shareView = share
//        addSubview(share)
    }

    func muteClick(button: UIButton) {
        button.isSelected = !button.isSelected
        player.isMuted = button.isSelected
    }
}

//MARK:手势
extension PlayerView : AliyunPVGestureViewDelegate {
    func onSingleClicked(withAliyunPVGestureView gestureView: AliyunPlayerViewGestureView!) {
        if lastOptiontime >= 5 {
            showRightNow()
        } else {
            hideRightNow()
        }
    }
    
    func onDoubleClicked(withAliyunPVGestureView gestureView: AliyunPlayerViewGestureView!) {
        puseOrStart()
    }
    
    func horizontalOrientationMoveOffset(_ moveOffset: Float) {
        if !canSeek(){return}
        var moveValue = self.bottomViewStartProgress + CGFloat(moveOffset) / self.frame.size.width;
        if moveValue > 1 { moveValue = 1 }
        if moveValue < 0 { moveValue = 0 }
        self.playerBottomView.ProgressView.progress = Float(moveValue);
        sliderVauleDidChange(value: Float(moveValue))
        playerBottomView.isDrag = true
        showRightNow()
    }
    
    // 手势开始
    func uiGestureRecognizerStateBegan(withAliyunPVGestureView gestureView: AliyunPlayerViewGestureView!) {
        if !canSeek(){return}
        bottomViewStartProgress = CGFloat(playerBottomView.ProgressView.progress);
        showRightNow()
    }
    
    // 手势结束
    func uiGestureRecognizerStateHorizontalEnded(withAliyunPVGestureView gestureView: AliyunPlayerViewGestureView!) {
        if !canSeek(){return}
        sliderDidEndDrag(value: playerBottomView.ProgressView.progress)
        playerBottomView.isDrag = false
        showRightNow()
    }
    
    //MARK:当前情况是否能seek
    func canSeek() -> Bool {
        if playStatus.value != AVPStatusPrepared && playStatus.value != AVPStatusStarted && playStatus.value != AVPStatusPaused{
            // 不满足这几种情况就不允许拖动
            return false
        }
        return true
    }
}
